<template>
  <div class="container">
    <div class="controls">
      <button @click="decreaseWater">减少水量</button>
      <span>当前水量: {{ waterLevel }}%</span>
      <button @click="increaseWater">增加水量</button>
    </div>
    <div class="cup-container">
      <canvas ref="waveCanvas" class="wave-canvas"></canvas>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'

const waveCanvas = ref(null)
const waterLevel = ref(50) // 初始水量50%
let ctx = null
let animationFrameId = null
const bubbles = ref([])

// 梯形尺寸常量
const CUP_TOP_WIDTH = 148
const CUP_BOTTOM_WIDTH = 116
const CUP_HEIGHT = 206
const CUP_BOTTOM_RADIUS = 32

// 生成梯形水杯形状路径
const generateCupPath = () => {
  const canvas = waveCanvas.value
  const centerX = canvas.width / 2
  const baseY = canvas.height

  // 计算梯形四个角的位置
  const topLeft = { x: centerX - CUP_TOP_WIDTH / 2, y: baseY - CUP_HEIGHT }
  const topRight = { x: centerX + CUP_TOP_WIDTH / 2, y: baseY - CUP_HEIGHT }
  const bottomRight = { x: centerX + CUP_BOTTOM_WIDTH / 2, y: baseY }
  const bottomLeft = { x: centerX - CUP_BOTTOM_WIDTH / 2, y: baseY }

  // 创建带圆角的底部路径
  ctx.beginPath()

  // 左上角到右上角
  ctx.moveTo(topLeft.x, topLeft.y)
  ctx.lineTo(topRight.x, topRight.y)

  // 右上角到右下角
  ctx.lineTo(bottomRight.x, bottomRight.y - CUP_BOTTOM_RADIUS)

  // 右下圆角
  ctx.quadraticCurveTo(bottomRight.x, bottomRight.y, bottomRight.x - CUP_BOTTOM_RADIUS, bottomRight.y)

  // 底部线
  ctx.lineTo(bottomLeft.x + CUP_BOTTOM_RADIUS, bottomRight.y)

  // 左下圆角
  ctx.quadraticCurveTo(bottomLeft.x, bottomRight.y, bottomLeft.x, bottomRight.y - CUP_BOTTOM_RADIUS)

  // 左下角到左上角
  ctx.lineTo(topLeft.x, topLeft.y)

  return { topLeft, topRight, bottomRight, bottomLeft }
}
// 获取当前水位高度
const getWaterHeight = () => {
  const canvas = waveCanvas.value
  return canvas.height - 20 - (CUP_HEIGHT * waterLevel.value) / 100
}

// 线性插值函数
const lerp = (start, end, t) => {
  return start * (1 - t) + end * t
}
// 重置水泡位置
const resetBubblePosition = (bubble, initial = false) => {
  const canvas = waveCanvas.value
  const waterHeight = getWaterHeight()

  // 在水杯底部到水位线之间随机位置
  const minY = waterHeight + 10 // 从水位线稍下方开始
  const maxY = canvas.height - 20 - bubble.radius // 到底部

  // 在水杯宽度范围内随机x位置（根据y位置处的宽度）
  const t = (canvas.height - 20 - bubble.y) / CUP_HEIGHT
  const currentWidth = lerp(CUP_BOTTOM_WIDTH, CUP_TOP_WIDTH, t)
  const minX = canvas.width / 2 - currentWidth / 2 + bubble.radius
  const maxX = canvas.width / 2 + currentWidth / 2 - bubble.radius

  bubble.x = minX + bubble.progress * (maxX - minX)

  if (initial) {
    // 初始位置在底部到水位线之间随机
    bubble.y = minY + Math.random() * (maxY - minY)
  } else {
    // 重置时放在接近底部位置
    bubble.y = maxY - Math.random() * 20
  }

  // 更新progress用于下次重置
  bubble.progress = Math.random()
}

// 更新水泡状态
const updateBubbles = () => {
  // 水量为0或100%时不显示水泡
  if (waterLevel.value <= 0 || waterLevel.value >= 100) {
    bubbles.value = []
    return
  }

  // 保持适当数量的水泡（根据水量调整）
  const targetCount = Math.floor((15 * waterLevel.value) / 100)

  // 移除多余的水泡
  if (bubbles.value.length > targetCount) {
    bubbles.value = bubbles.value.slice(0, targetCount)
  }
  // 添加不足的水泡
  else if (bubbles.value.length < targetCount) {
    const needed = targetCount - bubbles.value.length
    for (let i = 0; i < needed; i++) {
      bubbles.value.push(createBubble(true))
    }
  }

  // 确保所有水泡都在有效区域内
  bubbles.value.forEach(bubble => {
    if (!isBubbleInValidArea(bubble)) {
      resetBubblePosition(bubble)
    }
  })
}
// 初始化画布
const initCanvas = () => {
  const canvas = waveCanvas.value
  ctx = canvas.getContext('2d')

  // 设置canvas固定大小（根据水杯尺寸+边距）
  canvas.width = CUP_TOP_WIDTH + 40
  canvas.height = CUP_HEIGHT + 40

  // 初始化水泡
  updateBubbles()
}

// 创建新水泡
const createBubble = (initial = false) => {
  const bubble = {
    radius: Math.random() * 3 + 1,
    speed: Math.random() * 0.8 + 0.3,
    opacity: Math.random() * 0.5 + 0.3,
    sway: Math.random() * 0.1 - 0.05,
    progress: Math.random(),
    x: 0,
    y: 0
  }

  resetBubblePosition(bubble, initial)
  return bubble
}

// 检查水泡是否在有效区域（底部到水位线之间）
const isBubbleInValidArea = bubble => {
  const waterHeight = getWaterHeight()
  return bubble.y >= waterHeight && bubble.y <= waveCanvas.value.height - 20 - bubble.radius
}

// 检查点是否在水杯内
const isPointInCup = (x, y) => {
  const canvas = waveCanvas.value
  const centerX = canvas.width / 2
  const baseY = canvas.height - 20

  // 计算当前y位置对应的梯形宽度
  const t = (baseY - y) / CUP_HEIGHT
  if (t < 0 || t > 1) return false

  const currentWidth = lerp(CUP_BOTTOM_WIDTH, CUP_TOP_WIDTH, t)
  const left = centerX - currentWidth / 2
  const right = centerX + currentWidth / 2

  // 检查x是否在梯形范围内
  if (x < left || x > right) return false

  // 检查是否在底部圆角区域
  if (y > baseY - CUP_BOTTOM_RADIUS) {
    const bottomCenterY = baseY - CUP_BOTTOM_RADIUS
    const dx = Math.abs(x - centerX)
    const availableWidth = CUP_BOTTOM_WIDTH / 2 - CUP_BOTTOM_RADIUS

    if (dx > availableWidth) {
      const radiusAtX = Math.sqrt(Math.pow(CUP_BOTTOM_RADIUS, 2) - Math.pow(dx - availableWidth, 2))
      const minY = baseY - radiusAtX
      if (y < minY) return false
    }
  }

  return true
}

// 绘制水泡
const drawBubbles = () => {
  const canvas = waveCanvas.value
  const now = Date.now()
  const waterHeight = getWaterHeight()

  // 水量为0或100%时不绘制水泡
  if (waterLevel.value <= 0 || waterLevel.value >= 100) return

  bubbles.value.forEach(bubble => {
    // 更新位置
    bubble.y -= bubble.speed
    bubble.x += bubble.sway

    // 添加轻微摆动
    bubble.x += Math.sin(now * 0.001 + bubble.x * 0.01) * 0.3

    // 检查是否超出有效区域
    if (!isBubbleInValidArea(bubble)) {
      resetBubblePosition(bubble)
    }

    // 只绘制在水杯内的水泡
    if (isPointInCup(bubble.x, bubble.y)) {
      // 绘制水泡
      ctx.beginPath()
      ctx.arc(bubble.x, bubble.y, bubble.radius, 0, Math.PI * 2)
      ctx.fillStyle = `rgba(255, 255, 255, ${bubble.opacity})`
      ctx.fill()

      // 水泡高光
      ctx.beginPath()
      ctx.arc(bubble.x - bubble.radius * 0.3, bubble.y - bubble.radius * 0.3, bubble.radius * 0.2, 0, Math.PI * 2)
      ctx.fillStyle = `rgba(255, 255, 255, ${bubble.opacity + 0.2})`
      ctx.fill()
    }
  })
}
// 绘制水波
const drawWave = () => {
  const canvas = waveCanvas.value
  const waterHeight = getWaterHeight()
  const now = Date.now()

  ctx.clearRect(0, 0, canvas.width, canvas.height)

  // 绘制水杯轮廓
  ctx.save()
  generateCupPath()

  // 杯身填充色
  ctx.fillStyle = 'rgba(255, 255, 255, 0.2)'
  ctx.fill()

  // 杯身描边
  ctx.strokeStyle = 'rgba(100, 100, 100, 0.8)'
  ctx.lineWidth = 2
  ctx.stroke()

  // 创建剪切路径(限制水波和水泡在水杯内)
  ctx.clip()

  // 有水时才绘制水波
  if (waterLevel.value > 0) {
    // 绘制水波
    ctx.beginPath()
    const step = 5 // 水波绘制步长

    for (let x = 0; x < canvas.width; x += step) {
      if (!isPointInCup(x, waterHeight)) continue

      const y = waterHeight + Math.sin(x * 0.05 + now * 0.002) * 6 * (waterLevel.value / 100) + Math.sin(x * 0.1 + now * 0.001) * 3

      if (x === 0 || !isPointInCup(x - step, waterHeight)) {
        ctx.moveTo(x, y)
      } else {
        ctx.lineTo(x, y)
      }
    }

    // 闭合水波路径
    let lastX = canvas.width - 1
    while (lastX > 0 && !isPointInCup(lastX, waterHeight)) {
      lastX--
    }

    if (lastX > 0) {
      ctx.lineTo(lastX, canvas.height)
      ctx.lineTo(0, canvas.height)
      ctx.closePath()
    }

    // 水波渐变
    const waveGradient = ctx.createLinearGradient(0, waterHeight - 30, 0, waterHeight + 30)
    waveGradient.addColorStop(0, 'rgba(100, 200, 255, 0.8)')
    waveGradient.addColorStop(1, 'rgba(32, 132, 203, 0.6)')

    ctx.fillStyle = waveGradient
    ctx.fill()
  }

  ctx.restore()

  // 绘制水泡
  drawBubbles()
}

// 动画循环
const animate = () => {
  drawWave()
  animationFrameId = requestAnimationFrame(animate)
}

// 水量控制
const increaseWater = () => {
  waterLevel.value = Math.min(waterLevel.value + 10, 100)
}

const decreaseWater = () => {
  waterLevel.value = Math.max(waterLevel.value - 10, 0)
}

// 监听水量变化
watch(waterLevel, newVal => {
  updateBubbles()
})

onMounted(() => {
  initCanvas()
  animate()
})

onBeforeUnmount(() => {
  cancelAnimationFrame(animationFrameId)
})
</script>

<style>
/* .container {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 500px;
  padding: 20px;
  background: linear-gradient(to bottom, #f5f7fa, #c3cfe2);
} */

.controls {
  margin-bottom: 20px;
  display: flex;
  gap: 20px;
  align-items: center;
  background: white;
  padding: 10px 20px;
  border-radius: 30px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.cup-container {
  width: 188px; /* 比水杯最大宽度稍大 */
  height: 246px; /* 比水杯高度稍大 */
  position: relative;
  background: transparent;
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: flex-end;
}

.wave-canvas {
  width: 100%;
  height: 100%;
}

button {
  padding: 8px 16px;
  background-color: #4facfe;
  color: white;
  border: none;
  border-radius: 20px;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

button:hover {
  background-color: #3aa876;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

span {
  font-weight: bold;
  color: #333;
  min-width: 100px;
  text-align: center;
}
</style>
